<?php


namespace plugin\agent\event;


use app\common\service\ConfigService;
use app\model\order\Order;
use app\model\order\OrderDetail;
use app\model\user\User;
use Exception;
use plugin\agent\app\model\AgentGoods;
use plugin\agent\app\model\AgentOrder;
use plugin\agent\app\model\AgentUser;
use Psr\Log\LoggerInterface;
use support\Log;
use support\utils\Decimal;
use support\utils\Time;

class CalculateAgentOrder
{
    protected LoggerInterface $logger;

    /**
     * 计算分销
     * @param $order_no
     */
    public function execute($order_no)
    {
        $this->logger = Log::channel("agent");
        try {
            $this->logger->info("开始计算:[{$order_no}]");
            $this->calculate($order_no);
            $this->logger->info("结束计算:[{$order_no}]");
        } catch (Exception $exception) {
            $this->logger->error("计算分销异常:" . $exception->getTraceAsString());
        }
    }

    protected function calculate($order_no)
    {
        //查询配置
        $config = ConfigService::getConfig("AGENT_MODEL");
        if ($config && $config['open'] == 0) {
            $this->logger->info("分销配置未开启:[{$order_no}]");
            return;
        }
        $count = AgentOrder::where([
            'order_no' => $order_no
        ])
            ->count();
        if ($count > 0) {
            $this->logger->info("当前订单已经计算过分佣了:[{$order_no}]");
            return;
        }


        $detail = OrderDetail::where([
            'order_no' => $order_no
        ])
            ->field([
                'order_id',
                'goods_id',
                'goods_name',
                'sku_id',
                'sku_name',
                'num',
                'total_goods_price',
                'real_goods_price',
            ])
            ->select()
            ->toArray();

        $order = Order::where([
            'order_no' => $order_no
        ])
            ->field([
                'id',
                'order_no',
                'user_id',
            ])
            ->find();


        $agentGoods = AgentGoods::where([
            'goods_id' => array_column($detail, 'goods_id')
        ])
            ->with([
                'rule'
            ])
            ->select()
            ->toArray();
        if (!$agentGoods) {
            $this->logger->info("本单商品不涉及分销商品:[{$order_no}]");
            return;
        }
        $user = User::where([
            'id' => $order['user_id']
        ])
            ->field([
                'id',
                'commission_agent_id',
            ])
            ->find();
        if (!$user || !$user['commission_agent_id']) {
            $this->logger->info("本单用户没有绑定分销商:[{$order_no}]");
            return;
        }

        $two_agent_id = 0;
        $three_agent_id = 0;

        $agent_rebate_config = ConfigService::getConfig("AGENT_REBATE_CONFIG");

        $one = $this->getAgentUser([
            'agent_id' => $user['commission_agent_id']
        ]);
        $one_agent_id = $one['agent_id'] ?? 0;
        if ($config['layer'] == 2) {
            $two = $this->getAgentUser([
                'parent_agent_id' => $one['agent_id']
            ]);
            $two_agent_id = $two['agent_id'] ?? 0;
        }
        if ($config['layer'] == 3) {
            $two = $this->getAgentUser([
                'parent_agent_id' => $one['agent_id']
            ]);

            $three = $this->getAgentUser([
                'parent_agent_id' => $two['agent_id']
            ]);
            $two_agent_id = $two['agent_id'] ?? 0;
            $three_agent_id = $three['agent_id'] ?? 0;
        }

        $insert = [];

        $agentGoodsIds = array_column($agentGoods, 'goods_id');
        $agentGoods = array_column($agentGoods, null, 'goods_id');
        foreach ($detail as $item) {
            if (!in_array($item['goods_id'], $agentGoodsIds)) {
                continue;
            }
            $curAgentGoods = $agentGoods[$item['goods_id']] ?? [];
            if (!$curAgentGoods) {
                continue;
            }
            $one_rate = $curAgentGoods['one_rate'] ?? 0;
            $two_rate = $curAgentGoods['two_rate'] ?? 0;
            $three_rate = $curAgentGoods['three_rate'] ?? 0;
            if ($curAgentGoods['type'] == 1) {
                $one_rate = $curAgentGoods['rule']['one_rate'] ?? 0;
                $two_rate = $curAgentGoods['rule']['two_rate'] ?? 0;
                $three_rate = $curAgentGoods['rule']['three_rate'] ?? 0;
            }
            $calcMoney = $item['real_goods_price'];
            if ($agent_rebate_config['type'] == 1) {
                $calcMoney = $item['total_goods_price'];
            }
            $one_amount = Decimal::newDecimal($one_rate)->multiply($calcMoney)->divide(100)->getValue();
            $two_amount = Decimal::newDecimal($two_rate)->multiply($calcMoney)->divide(100)->getValue();
            $three_amount = Decimal::newDecimal($three_rate)->multiply($calcMoney)->divide(100)->getValue();
            $insert[] = [
                "order_id" => $order['id'],
                "order_no" => $order_no,
                "goods_id" => $item['goods_id'],
                "sku_id" => $item['sku_id'],
                "goods_name" => $item['goods_name'],
                "sku_name" => $item['sku_name'],
                "buy_user_id" => $order['user_id'],
                "order_amount" => $item['total_goods_price'] ?? 0,
                "pay_amount" => $item['real_goods_price'] ?? 0,
                "create_time" => Time::now(),
                "update_time" => Time::now(),
                "one_agent_id" => $one_agent_id,
                "one_rate" => $one_rate,
                "one_amount" => $one_amount,
                "two_agent_id" => $two_agent_id,
                "two_rate" => $two_rate,
                "two_amount" => $two_amount,
                "three_agent_id" => $three_agent_id,
                "three_rate" => $three_rate,
                "three_amount" => $three_amount,
                "total_agent_amount" => Decimal::newDecimal($one_amount)
                    ->add($two_amount)
                    ->add($three_amount)
                    ->getValue(),
            ];
        }
        AgentOrder::insertAll($insert);
    }

    private function getAgentUser($where)
    {
        return AgentUser::where($where)
            ->field([
                'agent_id',
                'user_id',
                'level_id',
            ])
            ->find();
    }
}